Skip to content

Add POST /companies/search (Preview)#599

Open
cox512 wants to merge 3 commits into
mainfrom
jacob.cox/companies-search
Open

Add POST /companies/search (Preview)#599
cox512 wants to merge 3 commits into
mainfrom
jacob.cox/companies-search

Conversation

@cox512

@cox512 cox512 commented Jul 20, 2026

Copy link
Copy Markdown

Why?

Companies can be listed via the API but not searched. This adds a "Search companies" operation for parity with "Search contacts", letting integrators find companies by custom attributes.

How?

Adds the /companies/search POST operation to the Preview API description.

Companion PRs & merge order

This change spans three repos. Merge in this order:

  1. intercom/intercom (monolith) — ships the behavior; must merge first -- https://github.com/intercom/intercom/pull/543548
  2. This PR intercom/Intercom-OpenAPI (public spec)
  3. intercom/developer-docs (reference + changelog): https://github.com/intercom/developer-docs/pull/1055

Merge #2 and #3 together, after this PR ships.

Generated with Claude Code

Generated via the generate-openapi-from-pr workflow from intercom/intercom
PR #543548. Documents the Preview /companies/search operation, reusing the
shared search_request and company_list schemas.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wgii8RHNriTrY4QtaJ4UDk
@cox512
cox512 requested review from a team July 21, 2026 16:44
shrek-intercom[bot]

This comment was marked as outdated.

@zilleeizad-inter zilleeizad-inter left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went deeper on spec-internal consistency beyond what shrek-intercom checked (shrek explicitly disables correctness review for this repo). Two findings, both example/error-shape issues rather than structural problems — the diff parses fine and all $refs resolve.

type: error.list
request_id: 8d6c1f0a-3b2e-4a17-9c5d-1f0e2a3b4c5d
errors:
- code: invalid_field

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Medium] The 400 error example introduces code: invalid_field, which is used nowhere else in this spec. The established convention for "this value/field isn't valid" errors elsewhere in descriptions/0/api.intercom.io.yaml is code: parameter_invalid (26 occurrences) or, less commonly, code: bad_request (e.g. the dataset_id "is not a valid" example at line ~1801). invalid_field doesn't match either pattern.

Since Shrek's correctness check is disabled for this repo, this is worth a manual check against the actual response shape from the companion monolith PR (intercom/intercom#543548) before merge — if the real API returns parameter_invalid, this example will mislead SDK consumers and fail validation against real behavior. Also, the error schema has an optional field property ("used to identify a particular field... that was in error") that this example leaves unset even though the whole point of the example is a bad field name — populating field: segment_id would make it more complete and consistent with how the schema is meant to be used.

operator: "="
value: my-company
pagination:
per_page: 5

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Low] The request example sets pagination.per_page: 5, but the paired 200 response example (same successful example key) still shows per_page: 15 (the default) instead of 5. Compare with the sibling /contacts/search endpoint, where the request example's per_page: 5 matches the response example's per_page: 5 exactly. Minor, but example pairs that don't agree with each other can trip up doc generators/SDK snippet tooling that pair request/response examples by key.

The request example sets pagination.per_page: 5, but the paired 200
response example showed per_page: 15. Match them (5) so request/response
example pairs agree, consistent with /contacts/search.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ATc7UmfbqPvfcrHccXaMPA
@cox512

cox512 commented Jul 23, 2026

Copy link
Copy Markdown
Author

Thanks @zilleeizad-inter — both looked at closely against the companion monolith PR (intercom/intercom#543548).

[Low] per_page mismatch — fixed in e69864a. The 200 example now shows per_page: 5 to match the request example, consistent with /contacts/search.

[Medium] code: invalid_field — verified correct as-is, keeping it. I traced the actual behavior rather than the spec-wide code distribution:

  • invalid_field is a registered, first-class code (app/lib/api/v3/errors/code.rb:45INVALID_FIELD = 'invalid_field').
  • It's the deliberate convention for the whole v3 search family, not a one-off — contacts/search, conversations/search, and now companies/search all raise it identically:
    # app/lib/api/v3/contacts/search/model/field.rb:28  (companies/search is a byte-for-byte copy)
    raise Api::V3::Errors::ApiCodedError.new(status: :bad_request, type: "invalid_field",
      message: "#{public_api_full_name} is not a valid search field") if data_attribute.blank? || INVALID_FIELDS.include?(field)
  • So /companies/search returns exactly what /contacts/search returns for a bad field — code: invalid_field, this same message. parameter_invalid is the convention for list/CRUD query-param validation, a different endpoint family; matching it here would actually break search-family consistency.
  • On the optional field property: ApiCodedError only carries status/type/message — none of the search validators populate field, so the real response omits it. Leaving it out keeps the example faithful to actual behavior.

(Side note: the existing /contacts/search spec only documents an invalid_sort_order 400 example, so this PR is actually more complete on the invalid-field case.)

~ Automated via Claude

shrek-intercom[bot]

This comment was marked as outdated.

Companies search accepts a sort object (validated server-side in
intercom/intercom#543548) but referenced the shared search_request
schema, which has no sort property. Add a company_search_request
schema mirroring contact_search_request, point the operation at it,
and document the sort object plus the tag_id filter-only-for-sort
caveat. Also call out that plan.id/plan.name are not searchable and
return 400 invalid_field.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ATc7UmfbqPvfcrHccXaMPA

@shrek-intercom shrek-intercom Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ PR Review Summary: APPROVE

Summary
🎯 Problem — Clear and well-structured problem statement that explains the gap (companies can be listed but not searched), the motivation (parity with contacts search, custom attribute filtering for integrators), and cross-repo context.
📝 Alignment — The description accurately matches the diff: a POST /companies/search operation and its companion company_search_request schema are added exclusively to the Preview API spec, with no omissions or phantom claims.
ℹ️ 🧠 Correctness — Disabled for this repository.
🦺 Safety — Purely additive change confined to the Unstable/Preview spec (version "0"), introducing a new POST /companies/search endpoint and a supporting schema without touching any released versions or existing definitions.
🚦 Auto-approval — Within size limit (0/150 LOC).
Per-criterion details

Problem

Clear problem statement (companies can be listed but not searched), explains the why (parity with contacts search, lets integrators find by custom attributes), and provides helpful context about cross-repo dependencies. Concise and well-structured without unnecessary verbosity.

Alignment

The PR description states that it adds a POST /companies/search operation to the Preview API description. The diff confirms:

  1. File changed: descriptions/0/api.intercom.io.yaml — this is indeed the Preview API spec (version "0" = Preview per the CLAUDE.md docs). ✓
  2. Operation added: A new /companies/search path with a post operation named searchCompanies is added with summary "Search companies". ✓
  3. Scope: The description says "for parity with Search contacts" — the endpoint structure (search by query with filters, pagination, sorting) mirrors how search endpoints typically work in this API. The description mentions operators, nesting, accepted fields, which is consistent with a search endpoint. ✓
  4. Supporting schema: A new company_search_request schema is added to components/schemas. This is not explicitly mentioned in the description but is a necessary part of adding the endpoint (it's the request body schema). This is a trivial implementation detail, not a significant omission.

The description accurately and completely describes the substantive change: adding a POST /companies/search endpoint to the Preview API specification. There are no phantom claims, no omissions of significant behavioral changes, and no scope mismatches.

Safety

This PR adds a new POST /companies/search endpoint exclusively to the Preview/Unstable spec (descriptions/0/api.intercom.io.yaml). The changes are purely additive:

  1. New endpoint: /companies/search POST operation with proper Intercom-Version header, tags, operationId, description, request body schema reference, and response examples (200, 401, 400).
  2. New schema: company_search_request in components/schemas that references existing schemas (single_filter_search_request, multiple_filter_search_request, starting_after_paging).

No existing endpoints, fields, or schemas are modified or removed. No released versions (descriptions/2.*/) are touched. No CI/CD files, scripts, Fern stable config, or dependency manifests are changed. This is a textbook example of an additive change confined to the Unstable/Preview tier, which is explicitly listed as safe to auto-approve.

<violated_criteria>
</violated_criteria>

Rate this comment 👍 / 👎 to help us improve 🙏 · Disagree with assessment? Establish ground truth here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants